<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Building a router</title>
    <script>
        // Put John's template engine code here...
        (function () {
            // A hash to store our routes:
            var routes = {};
            // The route registering function:
            function route (path, templateId, controller) {
                // Allow route(path, controller) for template less routes:
                if (typeof templateId === 'function') {
                    controller = templateId;
                    templateId = null;
                }
                routes[path] = {templateId: templateId, controller: controller};
            }
            var el = null, current = null;
            function router () {
                // Current route url (getting rid of '#' in hash as well):
                var url = location.hash.slice(1) || '/';
                // Get route by url:
                var route = routes[url];
                // Is it a route without template?
                if (route && !route.templateId) {
                    // Just initiate controller:
                    return route.controller ? new route.controller : null;
                }
                // Lazy load view element:
                el = el || document.getElementById('view');
                // Clear existing observer:
                if (current) {
                    Object.unobserve(current.controller, current.render);
                    current = null;
                }
                // Do we have both a view and a route?
                if (el && route && route.controller) {
                    // Set current route information:
                    current = {
                        controller: new route.controller,
                        template: tmpl(route.templateId),
                        render: function () {
                            // Render route template with John Resig's template engine:
                            el.innerHTML = this.template(this.controller);
                        }
                    };
                    // Render directly:
                    current.render();
                    // And observe for changes:
                    Object.observe(current.controller, current.render.bind(current));
                }
            }
            // Listen on hash change:
            this.addEventListener('hashchange', router);
            // Listen on page load:
            this.addEventListener('load', router);
            // Expose the route register function:
            this.route = route;
        })();
    </script>
    <script type="text/html" id="home">
        <h1>Router FTW!</h1>
    </script>
    <script type="text/html" id="template1">
        <h1>Page 1: <%= greeting %></h1>
        <p><%= moreText %></p>
    </script>
    <script type="text/html" id="template2">
        <h1>Page 2: <%= heading %></h1>
        <p>Lorem ipsum...</p>
    </script>
</head>
<body>
<ul>
    <li><a href="#">Home</a></li>
    <li><a href="#/page1">Page 1</a></li>
    <li><a href="#/page2">Page 2</a></li>
</ul>
<div id="view"></div>
<script>
    route('/', 'home', function () {});
    route('/page1', 'template1', function () {
        this.greeting = 'Hello world!';
        this.moreText = 'Loading...';

        // Simulating an Ajax call which take 0.5 s
        setTimeout(function () {
            this.moreText = 'Bacon ipsum...';
        }.bind(this), 500);
    });
    route('/page2', 'template2', function () {
        this.heading = 'I\'m page two!';
    });
</script>
</body>
</html>